
require('./function/function.js')
var fs = require("fs")


////////////////data////////////////////////
///_xxxx：前端专用数据 xxxx_:后端专用数据
var USERDATA =  
{   
    id:null,
    name:'',
    gold:100000,
    //state:'', // ready playing free(旁观也是free 只是有roomid)   不在线:offLine  玩家状态好像没什么用？
    roomId:1000 //1000表示无房间  旁观和桌上的玩家都需要改这个id
}

var ROOMDATA = {
        id:null,
        deskNum:3,
        bottomBet:10000, //goldlimit = 50*bottomBet
        desksData:{ //有一个玩家（ready或playing）就会塞入一个数据 索引是玩家的name,逻辑上是无序的
        },
        state:'', //playing（玩家加入时 不会改变desksData 只能旁观） free 玩家加入时，如果符合要求会加入desksData 
        countdownSeconds:-1, 
        // _countdownScheduler:null  //这个东西不能写在这里 函数里面会掉到ROOMDATA 就造成递归了 导致 Maximum call stack size exceeded
        cardsPool_:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51],
        _desksDataByIdx:[],// 客户端数据
        _currentRound:0,
    }

var deskDataModel = {
                cards:[[],[],[]], //1 尾道 2 中道 3 头道
                newRoundCards:[], 
                userData:{},
                userActionTimes_:0, //记录每局游戏中玩家操作次数 如果游戏结束还是0 则踢出
            }
        
////////////////data end////////////////////////

//初始化数据库
var daoInterface = require("./daoInterface")
daoInterface.initMysql()

//启动服务器
var server = require('http').createServer(requestListener)
var io = require('socket.io').listen(server)
server.listen(8888)

///////
function requestListener(request, response)
{	
	var router = require("./router")
	var requestHandlers = require("./requestHandlers")

	var handle ={}
	handle["/"]= requestHandlers.start
	var postData =""	
	router.route(handle, request.url, response, postData)
}

//全局变量
var users = {}  //键是name
//需要同步到数据库的 user数据包括gold,..(目前只有gold)
function updateUserGold(userName, gold)
{
    users[userName].gold = gold

    var sql = 'UPDATE `dbl`.`user` SET `gold` = ' + gold + ' WHERE `user`.`name` = ' + '"'+userName+'"' + ';'
    fs.appendFile('server/updateUserGold.log', sql)
}

function updateUserName(userName, name)
{
    users[userName].name = name
}


var rooms = []  //键是id  
rooms[1000] = null //从1001开始计数
var roomsData = [] //键是roomid  

var sockets = {}


//socket
io.sockets.on('connection', function(socket) {  //当有客户端连接时 执行以下函数

    console.log('Client connected')
    socket.send('Welcome client ')
    
//////////////////// server to client//////////////////////////

    socket.on('login', function(body) {
            body = eval("("+body+")")
            var name = body.name
            socket.name = name
            sockets[name] = socket
            if (users[name]) 
            {
                var userData = users[name]
                socket.emit('enterMainScene',{body:_filterData(userData)})

                var roomsList = _getRoomList(rooms)
                socket.emit('appendRoomsList',{body:_filterData(roomsList)})
            }
            else
            {
                var callBack = function(ret, userData)
                {   
                    if(ret==0)
                    {
                        users[name] = userData
                        socket.emit('enterMainScene',{body:_filterData(userData)})

                        var roomsList = _getRoomList(rooms)
                        socket.emit('appendRoomsList',{body:_filterData(roomsList)})
                    }
                    else
                    {
                        socket.emit('tips',{ret:ret})
                    }
                }
                daoInterface.getUserByNameAsyn(name, callBack)
            }
    })
    
    //如果玩家已有房间 直接将玩家送到那个房间
    socket.on('createRoom', function(body) {
            body = eval("("+body+")")
            _joinRoom(null,body)
    })


    socket.on('quickJoin', function() {
            var userData = users[socket.name]

            if (userData.roomId && rooms[userData.roomId])
            {   
                var desksData = rooms[userData.roomId].desksData
                if(desksData[userData.name])
                {
                    socket.join(userData.roomId)//断线了 要重新join
                    var roomData = rooms[userData.roomId]
                    socket.emit('showRoom',{body:_filterData(roomData)})
                    return 
                }
            }

            for(var i in rooms)
            {
                if (!rooms[i]) continue
                var roomData = rooms[i]
                var usingDeskNum = getObjLength(roomData.desksData)
                if (parseInt(roomData.bottomBet)*50<=parseInt(userData.gold)&&parseInt(roomData.deskNum) > parseInt(usingDeskNum))
                {   
                    _joinRoom(roomData)
                    return
                }
            }
            socket.emit('tips',{ret:'没有符合的房间'})
    })

    //gold和人数限制 全都服务器做 客户端不要去限制 
    //因为客户端数据可能错误 可能明明gold足够 不让人进来
    socket.on('joinRoom', function(body) {  
        body = eval("("+body+")")
        var roomData = rooms[body.id] 
        if(roomData)
        {
            _joinRoom(roomData) 
        }  
       
    })

    socket.on('leaveRoom', function() {
            var userData = users[socket.name]
            var roomData = rooms[userData.roomId]
            if (!userData.roomId || !roomData)
            {      
                userData.roomId = 1000
                socket.emit('hideRoom',{body:_filterData(userData)})
            }
            else
            {
                _leaveRoom()
            }

    })


    socket.on('chooseSure', function(body) {
        body = eval("("+body+")")
        _onChooseSure(body.cards)
    })

/////////////数据写入///////////////
   
    function _joinRoom(roomData,body)
    {   
        var userData = users[socket.name]
        //是否已有房间 已有房间 会去判断房间的desksdata里是否还有该玩家。 旁观的话有id desksdata中没有,还有掉线过长被踢出的也是
        //有的话会把玩家送到那个房间（关游戏，重进 ）没有的话可以进新房间
        if (userData.roomId && rooms[userData.roomId])
        {   
            var desksData = rooms[userData.roomId].desksData
            if(desksData[userData.name])
            {
                socket.join(userData.roomId)//断线了 要重新join
                var roomData = rooms[userData.roomId]
                socket.emit('showRoom',{body:_filterData(roomData)})
                return 
            }
        }


        if(!roomData) //不传roomdata 表示是新创建房间
        {   
            if ( parseInt(body.bottomBet)*50>parseInt(userData.gold) )
            {
                socket.emit('tips',{ret:'游戏币不足'})
                return 
            }
            var roomId = rooms.length
            //插入房间数据
            roomData = clone(ROOMDATA)
            rooms[roomId] = roomData
            roomData.id = roomId
            roomData.deskNum = body.deskNum
            roomData.bottomBet = body.bottomBet
            //appendRoomsList
            var rs = []
            rs[roomId] = rooms[roomId]
            var roomList = _getRoomList(rs)
            io.sockets.emit('appendRoomsList',{body:_filterData(roomList)})
        }

        ///游戏进行中或人数满或者gold不足，会被分配到旁观席位，否则上桌
        if(roomData.state=='playing'||getObjLength(roomData.desksData)==roomData.deskNum||parseInt(roomData.bottomBet)*50>parseInt(userData.gold))
        {   
            userData.roomId = roomData.id
            socket.emit('tips',{ret:'你进入旁观模式'})
            socket.join(roomData.id)
            socket.emit('showRoom',{body:_filterData(roomData)})
        }
        else
        {
            //更新数据
            userData.roomId = roomData.id
            var deskData = clone(deskDataModel)
            deskData.userData = userData
            deskData.userActionTimes_ = 0
            roomData.desksData[userData.name] = deskData

            socket.join(roomData.id)
            socket.emit('showRoom',{body:_filterData(roomData)})
            if (getObjLength(roomData.desksData)>1)
            {   
                _newRoundCountdown(roomData.id,5)
            }
        }
        //
        socket.broadcast.in(roomData.id).emit('refreshRoom',{body:_filterData(roomData)})
    }

    function _leaveRoom()
    {   
        var userData = users[socket.name]
        var roomData = rooms[userData.roomId]
        var desksData = roomData.desksData
            
        //如果是旁观可以任意进出。
        //如果在桌子上：
        //1、房间在playing状态时退出 会扣去bet*50的gold 并提示tips 。否则可以直接退出
        //2、如果玩家在一局游戏中，一次操作都没有(直接关游戏了) 这局结束时（正常结束） 会把玩家踢出房间
        if(!desksData[userData.name])
        {
            userData.roomId = 1000
            socket.leave(roomData.id)
            socket.emit('hideRoom',{body:_filterData(userData)})
        }
        else
        {   
            if(roomData.state=='playing')
            {
                updateUserGold(userData.name, parseInt(userData.gold) - parseInt(roomData.bottomBet)*50)
                socket.emit('tips',{ret:'游戏进行中退出,游戏币-' + (parseInt(roomData.bottomBet)*50)})
                socket.broadcast.in(roomData.id).emit('tips',{ret:'有玩家中途退出,本局游戏结束'})
                _resetGameForOver(roomData)
            }
            else
            {
            }
            //更新数据
            userData.roomId = 1000
            delete roomData.desksData[userData.name]
            //
            socket.leave(roomData.id)
            socket.emit('hideRoom',{body:_filterData(userData)})
            
            //
            var usingDeskNum = getObjLength(roomData.desksData)
            if (usingDeskNum>1)
            {   
                io.sockets.in(roomData.id).emit('refreshRoom',{body:_filterData(roomData)})
                _newRoundCountdown(roomData.id,5)
            }
            else
            {   
                roomData.countdownSeconds = -1
                if( roomsData[roomData.id] )
                    clearInterval(roomsData[roomData.id].newRoundInterval) 
                io.sockets.in(roomData.id).emit('refreshRoom',{body:_filterData(roomData)})
                io.sockets.in(roomData.id).emit('refreshCountdown',{body:roomData.countdownSeconds})
            }

        }
    }


    //每当玩家加入房间时，如果房间人数2人以上，会有倒计时3秒 如果本身就在倒计时 这个倒计时会刷新成3秒
    //每当玩家退出房间时，如果房间人数2人以上，会有倒计时3秒 如果本身就在倒计时 这个倒计时会刷新成3秒。 如果只剩下1人倒计时删除
    //新一局倒计时
    function _newRoundCountdown(roomId,seconds)
    {   
        var roomData = rooms[roomId]
        roomsData[roomData.id] = roomsData[roomData.id] || []

        if(roomsData[roomData.id].newRoundInterval)  //如果先后有人进房间 会多次调用这个函数
            clearInterval(roomsData[roomData.id].newRoundInterval) 

        roomData.countdownSeconds = seconds
        io.sockets.in(roomData.id).emit('refreshCountdown',{body:roomData.countdownSeconds})

        //返回值是一个int型 idx
        roomsData[roomData.id].newRoundInterval = setInterval( 
            function() {
                    roomData.countdownSeconds =  roomData.countdownSeconds - 1
                    io.sockets.in(roomData.id).emit('refreshCountdown',{body:roomData.countdownSeconds})
                    if (roomData.countdownSeconds==-1)
                    {   
                        clearInterval(roomsData[roomData.id].newRoundInterval)
                        _newRound(roomId)
                    }
               }, 1000)
    }



    //服务器发牌并起一个延时函数 在30秒后更新countdownSeconds=10 并emit refreshCountdown 
    //倒计时结束无论有没有摆好 服务器会为玩家随机摆  将数据更新 并进入下回合                        
    //客户端根据newRoundCards摆牌，当客户端确认摆牌请求服务器时，服务器检查是否所有玩家都摆好，摆好则将数据更新 删除计时器  并进入下回合  
    function _newRound(roomId)
    {
        var roomData = rooms[roomId]
        var desksData = roomData.desksData
        var length = null
        for(var i in desksData)
        {   
            var length = desksData[i].cards[0].length + desksData[i].cards[1].length + desksData[i].cards[2].length
            break
        }
        if (length<13)
        {
            _dealCards(roomId)
        }
        else
        {
            _showGameResult(roomId)
        }
    }

    //游戏结束。 计算大小，更新数据 ， 弹出结算表 然后下一局倒计时 倒计时结束后自动开始下一局
    function _showGameResult(roomId)
    {  
        var roomData = rooms[roomId]
        var desksData = roomData.desksData
        var cardsType = ['','高牌','一对','两对','三条','顺子','同花','葫芦','四条','同花顺','皇家同花顺']
        //resultData[0] 结构： [ID,结果,头道,中道,尾道,全胜,特殊牌型,总分,游戏币]
        var resultData = [] 
        for(var i in desksData)
        {   
            var l = resultData.length
            resultData[l] = []
            resultData[l][0] = i
            resultData[l].cards_ = clone(desksData[i].cards)
        }

        for(var i in resultData)
        {   
            var cards = resultData[i].cards_
            resultData[i][1] = (_campareTwoCardsScores(cards[0], cards[1])&&_campareTwoCardsScores(cards[1], cards[2]) )?'成牌':'倒牌' 
            for(var j in cards)
            {
                resultData[i][4-j] = cardsType[  _getCardsTypeScores(cards[j])[0]  ]
            }

            if (resultData[i][1]=='倒牌')
            {
                resultData[i].cards_ = [[-1],[-1],[-1]]
            }
        }
        /**
         * [updateResultData234 
            头中尾计算 
            根据玩家的排名先后分别给一个初始分   
            从末尾开始给分 如果没成牌直接0分 否则这个分累加 最后一名0分 倒数第二名1分 倒数第三名2分
            如果没成牌 都算0分 可能多个没成牌
            根据初始分得到头中尾道分
            头中尾分 =  （自己的初始分 - 所有玩家初始分总和/玩家数） * 玩家数）
         * ]
         * @param  {[type]} idx [description]
         * @return {[type]}     [description]
         */
        function updateResultData234(idx) //idx = 2,3,4
        {   
            var idxInCards = 4-idx

            resultData.sort(function(a,b)
                {   
                    return _campareTwoCardsScores( a.cards_[idxInCards],b.cards_[idxInCards] )
                })

            var scores = []
            var score = 0
            var totalScore = 0
            for(var i=0;i<resultData.length;i++)
            {   
                scores[i] = score
                totalScore = totalScore + score
                if ( resultData[i+1] && resultData[i+1][1]=='倒牌' ); //如过下面一个是倒牌 则下面一个的score也是0
                else
                {
                    score = score + 1
                }
            }
           
            for(var i=0;i<resultData.length;i++)
            {   
                resultData[i][idx] = resultData[i][idx] + _numWithSign( ( (scores[i]-totalScore/resultData.length)*resultData.length ) )
            }
        }
        updateResultData234(2)
        updateResultData234(3)
        updateResultData234(4)

        //如果 头中尾都大于0（头分大于0的只可能有一个 因为不可能有一样大的牌型） 则获得全胜分 = (n-1)
        //其他人分数 负的(n-1)/(n-1)
        function updateResultData5() //idx = 2,3,4
        {   
            for(var i in resultData)
            {   
                resultData[i][5] = 0

                var headScore =  parseInt( resultData[i][2].substr(-2,2) ) 
                var middleScore =  parseInt( resultData[i][3].substr(-2,2)  ) 
                var tailScore =  parseInt( resultData[i][4].substr(-2,2)  ) 

                if (headScore>0&&middleScore>0&&tailScore>0)
                {
                    for(var j in resultData)
                    {   
                        resultData[j][5] = -1
                    }
                    resultData[i][5] = _numWithSign ( (resultData.length-1) )
                    break
                }
            }
        }

        updateResultData5()


        // 玩家的牌型分 = 人数*自己牌型分 - 总分  
        // (自己牌型分 - 平均牌型分) * 人数
        function updateResultData6() 
        {   
            var scores = []
            var totalScore = 0

            for(var i in resultData)
            {   

                if (resultData[i][1] == '倒牌')
                {
                    scores[i] = 0
                }
                else
                {   
                   scores[i] = getTypeScores(0,resultData[i].cards_[0]) + getTypeScores(1,resultData[i].cards_[1]) + getTypeScores(2,resultData[i].cards_[2])
                }
                totalScore = totalScore + scores[i]
            }

            for(var i in resultData)
            {   
                resultData[i][6] = _numWithSign( resultData.length*scores[i] - totalScore )
            }   
        }

        function getTypeScores(idx,cards)// 0,1,2 尾道 中道 头道
        {  
            var cardsType = ['','高牌','一对','两对','三条','顺子','同花','葫芦','四条','同花顺','皇家同花顺']

            var table = [
            [0,0,0,0,0,2,4,6,10,15,25],
            [0,0,0,0,2,4,8,12,20,30,50]]
            if(idx==2)
            {
                var type = _getCardsTypeScores(cards)[0]
                if(type==2)
                {
                    var cardIdx = Math.round(_getCardsTypeScores(cards)[1]/2)
                    var num =  getNumAndColorByCardIdx(cardIdx)[0]
                    if (num>5)
                        return num - 5
                }
                else if (type==4)
                {
                    var cardIdx = _getCardsTypeScores(cards)[1]
                    var num =  getNumAndColorByCardIdx(cardIdx)[0]
                    return num + 8
                }
                return 0
            }
            else
            {
                return table[idx][ _getCardsTypeScores(cards)[0] ]
            }
        }
                   
        updateResultData6()

        for(var i in resultData)
        {   
            var headScore =  parseInt( resultData[i][2].substr(-2,2) ) 
            var middleScore =  parseInt( resultData[i][3].substr(-2,2)  ) 
            var tailScore =  parseInt( resultData[i][4].substr(-2,2)  ) 

            resultData[i][7] = _numWithSign( headScore + middleScore + tailScore + parseInt(resultData[i][5]) + parseInt(resultData[i][6]) )
            resultData[i][8] = _numWithSign( resultData[i][7]  * roomData.bottomBet )
            
            updateUserGold(resultData[i][0], parseInt(users[resultData[i][0]].gold) + parseInt( resultData[i][8] ))
        } 

        for(var i in desksData)
        {
            if(desksData[i].userActionTimes_==0)
            {
                desksData[i].userData.roomId = 1000
                sockets[desksData[i].userData.name].emit('hideRoom',{body:_filterData(desksData[i].userData)})
                sockets[desksData[i].userData.name].leave(roomData.id)
                delete  desksData[i]   
            }
        }

        io.sockets.in(roomData.id).emit('showGameResult',{body:_filterData(resultData)})
        
        //更新roomData
        io.sockets.in(roomData.id).emit('refreshRoom',{body:_filterData(roomData)}) 

        _resetGameForOver(roomData)

        var usingDeskNum = getObjLength(roomData.desksData)
        if(usingDeskNum>1)
            _newRoundCountdown(roomData.id,10)

    }
    
    function _dealCards(roomId)
    {   
        var roomData = rooms[roomId]
        if(roomData.state=='free'||!roomData.state) roomData.state = 'playing'   

        function pick(num)
        {
            for(var i in roomData.desksData)
            {
                var newRoundCards = roomData.desksData[i].newRoundCards
                for(var j=0;j<num;j++)
                {
                    newRoundCards[j] = _pickOneCard(roomData.cardsPool_) 
                }
            }
            io.sockets.in(roomData.id).emit('dealCards',{body:_filterData(roomData)}) 
            _autoChooseCountdown(roomData.id)
        }

        if(roomData.cardsPool_.length==52) //第一轮
        {   
            pick(5)
        }
        else
        {
            pick(3)
        }

    }

    function _onChooseSure(cards)
    {   
        var userData = users[socket.name]
        var roomData = rooms[userData.roomId]
        var desksData = roomData.desksData

        //更新数据
        desksData[userData.name].userActionTimes_ = desksData[userData.name].userActionTimes_ + 1
        desksData[userData.name].cards = cards
        desksData[userData.name].newRoundCards = []
        //console.log('cards:',cards)

        //是否可以下一轮
        var length = null
        var isChoosedAll = true
        for(var i in desksData)
        {   
            var l = desksData[i].cards[0].length + desksData[i].cards[1].length + desksData[i].cards[2].length
            if(length!=null && length != l)
            {    
                isChoosedAll = false
                break
            }
            length = l
        }
        if(isChoosedAll)
        {   
            roomData.countdownSeconds = - 1
            clearTimeout(roomsData[roomData.id].autoChooseTimeout)
            clearInterval(roomsData[roomData.id].autoChooseInterval)
            io.sockets.in(roomData.id).emit('refreshCountdown',{body:roomData.countdownSeconds})
            _newRound(roomData.id)
        }
        else
        {     
            socket.emit('refreshRoom',{body:_filterData(roomData)})
        }
    }

     function _autoChooseCountdown(roomId) 
     {  
        var roomData = rooms[roomId]
        roomsData[roomData.id] = roomsData[roomData.id] || []

        if(roomsData[roomData.id].autoChooseTimeout)  //如果先后有人进房间 会多次调用这个函数
            clearTimeout(roomsData[roomData.id].autoChooseTimeout) 

        roomsData[roomData.id].autoChooseTimeout = setTimeout(
            function() {
                    clearTimeout(roomsData[roomData.id].autoChooseTimeout )
                    if(roomsData[roomData.id].autoChooseInterval)  //如果先后有人进房间 会多次调用这个函数
                        clearInterval(roomsData[roomData.id].autoChooseInterval) 

                    roomData.countdownSeconds = 10
                    io.sockets.in(roomData.id).emit('refreshCountdown',{body:roomData.countdownSeconds})
                    roomsData[roomData.id].autoChooseInterval = setInterval(
                    function() {
                            roomData.countdownSeconds =  roomData.countdownSeconds - 1
                            io.sockets.in(roomData.id).emit('refreshCountdown',{body:roomData.countdownSeconds})
                            if (roomData.countdownSeconds==-1)
                            {   
                                clearInterval(roomsData[roomData.id].autoChooseInterval)
                                //倒计时结束无论有没有摆好 服务器会为玩家随机摆 并进入下回合   
                                _autoChoose(roomId) 
                                io.sockets.in(roomData.id).emit('refreshRoom',{body:_filterData(roomData)}) 
                                _newRound(roomId)
                            }

                       }, 1000)
               }, 10000)
     }


//////////////////// server to client end//////////////////////////
     


    ///
    ///大菠萝规则
    //1. 每位玩家分别与其他玩家比较每一道牌（头道，中道，底道）的牌型大小。每道获胜玩家拿到1分的基础道计分。
    //如果玩家三道全部获胜将会得到3分的全胜分。  
    //2. 每道摆出规定特殊牌型的玩家会得到特殊牌型的附加计分。



///////////////////////functions for [server to client]/////////////////
    
    //过滤服务器专用数据 
    function _filterData(data)
    {   
        function filter(d)
        {
            for(var i in d)
            {   
                if(i[i.length-1]=='_')
                {   
                    delete d[i]
                }
                else if (typeof(d[i]) == "object")
                {   
                    filter(d[i])
                }
            }
            return d
        }

        var d = filter(clone(data))
        return d
    }

    function _numWithSign(num)
    {   
        return parseInt(num)>=0?('+'+num):num
    }

    function _getRoomList(rooms)
    {   
        var rl = []
        for(var i in rooms)
        {   
            if(i == 1000) continue
            var length = rl.length
            rl[length] = {}
            rl[length].id = rooms[i].id
            rl[length].deskNum = rooms[i].deskNum
            rl[length].bottomBet = rooms[i].bottomBet
        }
        return rl
    }

    function _resetGameForOver(roomData)
    {   
        if(roomsData[roomData.id].autoChooseTimeout)  
            clearTimeout(roomsData[roomData.id].autoChooseTimeout) 
        if(roomsData[roomData.id].autoChooseInterval) 
            clearInterval(roomsData[roomData.id].autoChooseInterval) 

        roomData.countdownSeconds = -1
        roomData.state = 'free'
        roomData.cardsPool_ = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51]
        for(var i in roomData.desksData)
        {
          roomData.desksData[i].cards = [[],[],[]]
          roomData.desksData[i].newRoundCards = []
          roomData.desksData[i].userActionTimes_ = 0
        }
    }

    function _pickOneCard(cardsPool) 
    {   
        var cpLength = cardsPool.length
        var randomCardIdx = Math.ceil((Math.random()*cpLength))
        if(randomCardIdx == 0) randomCardIdx = 1
        randomCardIdx = randomCardIdx - 1
        return cardsPool.splice(randomCardIdx,1)[0]
    }

    function _autoChoose(roomId) 
    {   
        var roomData = rooms[roomId]
        //更新  cards 和   newRoundCards                  
        for(var i in roomData.desksData)
        {   
            var deskData = roomData.desksData[i]
            
            //更新 newRoundCards
            var choosedCards = clone(deskData.newRoundCards)
            deskData.newRoundCards = []

            if(choosedCards.length!=5)
            {
                var passCardIdx = Math.ceil((Math.random()*3))
                if(passCardIdx == 0) passCardIdx =1
                passCardIdx = passCardIdx -1    
                choosedCards.splice(passCardIdx,1)
            }

            //更新 cards
            var cards = deskData.cards
            for(var x=0;x<3;x++)    
            {   
                var chooseLength = choosedCards.length
                if (chooseLength==0) break

                var c = cards[x]
                for(var y=0;y<chooseLength;y++)
                {
                      if(c.length!=5)
                      {
                          c[c.length] = choosedCards.splice(0,1)[0]
                      }
                      else
                      {
                          break
                      }
                }
            }
        }
    }


    //如果cards1大返回true
    function  _campareTwoCardsScores(cards1, cards2)  
    {
        var scores1 = _getCardsTypeScores(cards1)
        var scores2 = _getCardsTypeScores(cards2)

        if(scores1[0]!=scores2[0])
        {   
            return scores1[0]>scores2[0]?true:false
        }
        else if (scores1[1]!=scores2[1])
        {
            return scores1[1]>scores2[1]?true:false
        }
        else if (scores1[2]!=scores2[2])
        {
            return scores1[2]>scores2[2]?true:false
        }
        else if (scores1[3]!=scores2[3])
        {
            return scores1[3]>scores2[3]?true:false
        }
        else if (scores1[4]!=scores2[4])
        {
            return scores1[4]>scores2[4]?true:false
        }

        return true

    }

    /**
     * [_campareCardsScores 
     * 传入cards数组 
     * 函数会将这个数组按牌型大小做好排序
     * ]
     * @param  {[array]} cardsArray  [[1,2,3,4,5],[3,1,4,5,1],....]
     * @return 
     */
    function  _campareCardsScores(cardsArray)  
    {
        cardsArray.sort(function(a,b)
            {   
                //return _campareTwoCardsScores(a, b)==1?true:false  
                return _campareTwoCardsScores(a, b)
            })
    }

    /**
     * [_getCardsTypeScores 
     * 黑桃>红桃>梅花>方块  每张牌都有自身的分值 比如方块2最最小算0分 ，梅花2算1分，。。
     * cardsPool_中cardIdx和这个分值对应 方便处理  所以对应关系是 [0=2,1=2,2=2,3=2,4=3,5=3,6=3,7=3......51=A]
     * ]
     * @param c [0,1,2,3,4]
     * @return
     */
    function  _getCardsTypeScores(c)  
    {

        if (c[0] == -1) //倒牌
            return [0]

        var cards = clone(c)
        cards.sort(function(a,b){return a>b?true:false})
       
        var scores = [null,null,null] 
        //牌型分值分多段 比大小小时从前往后比 直到必出大小
        //第一段 一对 两对 三条 高牌 顺子 同花 葫芦 四条 同花顺 皇家同花顺 牌型分:12345678910
        //
        if(hasHjths(cards)[0])
        {
            scores[0] = 10
        }
        else if(hasThs(cards)[0])
        {
            scores[0] = 9
            scores[1] = hasThs(cards)[1][0]
        }
        else if(hasSitiao(cards)[0])
        {
            scores[0] = 8
            scores[1] = hasSitiao(cards)[1][0]
        }
        else if(hasHulu(cards)[0])
        {
            scores[0] = 7
            scores[1] = hasHulu(cards)[1][0][0]
        }
        else if(hasTonghua(cards)[0]) //两个同花比大小 看最大一张
        {
            scores[0] = 6
            scores[1] = hasTonghua(cards)[1][4]
        }
        else if(hasShunzi(cards)[0])//两个顺子比大小 看最大一张
        {
            scores[0] = 5
            scores[1] = hasShunzi(cards)[1][4]
        }
        else if(hasSantiao(cards)[0])
        {
            scores[0] = 4
            scores[1] = hasSitiao(cards)[1][0]
        } 
        else if(hasLiangdui(cards)[0]) //两对比大小 要看两个对 
        {   
            var t = hasLiangdui(cards)
            scores[0] = 3
            scores[1] = t[1][0][0]  + t[1][0][1]
            scores[2] = t[1][1][0]  + t[1][1][1]
            scores[3] = t[2]
        } 
        else if(hasYidui(cards)[0])
        {
            var t = hasYidui(cards)
            scores[0] = 2
            scores[1] = t[1][0]  + t[1][1] 
            scores[2] = t[2]
        } 
        else 
        {
            scores[0] = 1
            scores[1] = cards[cards.length-1]
        }
        return scores
    }

///////////////////////functions for [server to client] end/////////////////

/////////////////////for _getCardsTypeScores//////////////////////////
//cardIdx 比如方片2对应0 黑桃A对应51
//cardNum 2 3 4 5 6....14(A对应14)

    function  getNumAndColorByCardIdx(cardIdx)
    {
        var num = Math.ceil((cardIdx+1)/4) + 1  //11 12  13  14 对应j q k a
        var color = cardIdx%4  // 0 1 2 3对应方块 梅花 红桃 黑桃
        return [num,color]
    }

    function  getCardIdxByColorAndNum(num, color)
    {
        return (num-2)*4 + color
    }
    //将cards 按cardNum分组
    function  getGroupedCards(cards)
    {
        var a = []  //[[0,1],[5],[10],[32]]

        for(var i in cards)  //遍历cards 将card分组
        {
            var numExistedInA = false
            for(var j in a)
            {
                var num = getNumAndColorByCardIdx(a[j][0])[0]
                if (getNumAndColorByCardIdx(cards[i])[0] == num) //如果cards[i] 
                {
                    a[j][a[j].length] = cards[i]
                    numExistedInA = true
                    break
                }
            }
            if(!numExistedInA)
            {   
                var newIdx = a.length
                a[newIdx] = []
                a[newIdx][0] = cards[i]
            }
        }

        return a
    }

    //
    /**
     * [hasSameCardNum 
     * 判断cards中是否有相同的牌 返回相同牌的数组和这组牌中最大单牌（注意：如果有两个结果 只会返回一个 比如两对）
     * ]
     * @param  {[type]}  cards [description]
     * @param  {[type]}  num   有几个
     * @return {Boolean}       [description]
     */
    function  hasSameCardNum(cards,num) 
    {
        var c = getGroupedCards(cards)
        var typeCardIdxs = []
        var maxSingleCardIdx = 0

        var isExisted = false
        for(var i in c)
        {   
            if (c[i].length>=num)
            {
                typeCardIdxs = c[i]
                isExisted = true
            }
            else
            {
                maxSingleCardIdx = Math.max(maxSingleCardIdx, c[i][0])
            }
        }

        return [isExisted,typeCardIdxs,maxSingleCardIdx]
    }

    //下面的函数不是用来最终确定牌型的 用来确定是否包含某个牌型 因为这样大的的牌型判断可以复用 小的牌型判断函数
    //同时返回组成牌型的card数组 和 最大单牌
    function  hasYidui(cards)
    {
        return hasSameCardNum(cards,2) 
    }

    function  hasLiangdui(cards) //两对返回的组成牌型的card数组 包含了两个数组
    {   
        if(cards.length==3)
            return [false]
        var c = getGroupedCards(cards)

        var typeCardIdxs = []
        var maxSingleCardIdx = 0
        var duiNum = 0
        for(var i in c)
        {   
            if (c[i].length>=2)
            {
                typeCardIdxs[typeCardIdxs.length] = c[i]
                duiNum = duiNum + 1
            }
            else
            {
                maxSingleCardIdx = Math.max(maxSingleCardIdx, c[i][0])
            }
        }

        if(duiNum==2)
        {
            var a = typeCardIdxs[0][0]
            var b = typeCardIdxs[1][0]
            if (b>a)
            {
                var t = typeCardIdxs[0]
                typeCardIdxs[0] = typeCardIdxs[1]
                typeCardIdxs[1] = t

            }
            return [true,typeCardIdxs,maxSingleCardIdx]
        } 
        else
        {
            return [false]
        }
    }

    function  hasSantiao(cards)
    {
        return hasSameCardNum(cards,3) 
    }
    
    function  hasShunzi(cards)
    {
        if(cards.length==3)
            return [false]
        if(getNumAndColorByCardIdx(cards[1])[0] == 1 + getNumAndColorByCardIdx(cards[0])[0]&&
           getNumAndColorByCardIdx(cards[2])[0] == 2 + getNumAndColorByCardIdx(cards[0])[0]&&
           getNumAndColorByCardIdx(cards[3])[0] == 3 + getNumAndColorByCardIdx(cards[0])[0]&&
           getNumAndColorByCardIdx(cards[4])[0] == 4 + getNumAndColorByCardIdx(cards[0])[0])
        {
            typeCardIdxs = clone(cards)
            return [true,typeCardIdxs]
        }
        else
        {
            return [false]
        }
    }
    
    function  hasTonghua(cards)
    {
        if(cards.length==3)
            return [false]
        if(getNumAndColorByCardIdx(cards[1])[1] == getNumAndColorByCardIdx(cards[0])[1]&&
           getNumAndColorByCardIdx(cards[2])[1] == getNumAndColorByCardIdx(cards[0])[1]&&
           getNumAndColorByCardIdx(cards[3])[1] == getNumAndColorByCardIdx(cards[0])[1]&&
           getNumAndColorByCardIdx(cards[4])[1] == getNumAndColorByCardIdx(cards[0])[1])
        {
            typeCardIdxs = clone(cards)
            return [true,typeCardIdxs]
        }
        else
        {
            return [false]
        }

    }
    
    function  hasHulu(cards)
    {   
        if(cards.length==3)
            return [false]
        var a = hasLiangdui(cards) 
        var b = hasSameCardNum(cards,3)

        var isExisted = a[0] && b[0]
        var typeCardIdxs = []
        if(isExisted)
        {
            if (a[1][0].length==3)
            {
                typeCardIdxs[0] = a[1][0]
                typeCardIdxs[1] = a[1][1]
            }
            else
            {
                typeCardIdxs[0] = a[1][1]
                typeCardIdxs[1] = a[1][0]
            }

            return [true, typeCardIdxs]
        } 
        else
        {
            return [false]
        }
    }
    
    function  hasSitiao(cards)
    {
        if(cards.length==3)
            return [false]
        return hasSameCardNum(cards,4)
    }
    
    function  hasThs(cards)
    {   
        if(cards.length==3)
            return [false]
        var a = hasShunzi(cards) 
        var b = hasTonghua(cards)

        if (a[0]&&b[0])
        {
            return a
        }
        else
        {
            return [false]
        }
    }
    
    function  hasHjths(cards)
    {
        if(cards.length==3)
            return [false]
        if (cards[0]== getCardIdxByColorAndNum(10, 3)&&
            cards[1]== getCardIdxByColorAndNum(11, 3)&&
            cards[2]== getCardIdxByColorAndNum(12, 3)&&
            cards[3]== getCardIdxByColorAndNum(13, 3)&&
            cards[4]== getCardIdxByColorAndNum(14, 3) )
        {
            return [true,clone(cards)] 
        }
        else
        {
            return [false] 
        }
    }

/////////////////////for _getCardsTypeScores end//////////////////////////


})
